package com.zhj.threadpoolboot.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhj.threadpoolboot.service.TestService;
import jakarta.annotation.Resource;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@RestController
public class TestController {
    private static Logger log = LoggerFactory.getLogger(TestController.class);
    @Resource
    TestService testService;
    @Resource(name = "threadPoolExecutor")
    private ThreadPoolTaskExecutor taskExecutor;

    //   调用方式0
    @RequestMapping("start")
    public String start() throws ExecutionException, InterruptedException {

        List<String> list = Stream.generate(() -> "101010200")
                .limit(100000).toList();

        Console.log("城市数量：%s   ", list.size());

        String startTime = DateUtil.now();

        for (String code : list) {
            Future<String> future = taskExecutor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
//                    log.info("开始请求 {}",code);
                    Thread.sleep(2000);
                    String weather = testService.doRequest(String.format("http://t.weather.sojson.com/api/weather/city/%s", code));
                    JSONObject json = JSONUtil.parseObj(weather);
                    if (json.getInt("status") == 403) {
                        return "";
                    }
                    String city = json.getJSONObject("cityInfo").getStr("city");
                    String cityInfo = String.format("城市：%s  , 城市数据：%s", city, json.getJSONObject("cityInfo"));
//                    log.info("请求结果 {}",cityInfo);
                    return cityInfo;
                }
            });


        }
        String endTime = DateUtil.now();

        long betweenSecond = DateUtil.between(DateUtil.parse(startTime), DateUtil.parse(endTime), DateUnit.SECOND);

        // 气象城市 https://blog.csdn.net/qq893858710/article/details/7419329
        return String.format("开始时间=%s, 结束时间=%s, 总共花费 ： %s 秒", startTime, endTime, betweenSecond);
    }



    //   调用方式1，内部调用async失效
    @RequestMapping("start1")
    public String start1() throws InterruptedException {
        List<String> list = Stream.generate(() -> "101010200")
                .limit(100000).toList();

        Console.log("城市数量：%s   ", list.size());
        for (String code : list) {
            asyncMethod(code);
        }
        return "SUCCESS";
    }


    @Async("threadPoolExecutor")
    public CompletableFuture<String> asyncMethod(String code) throws InterruptedException {
        log.info("开始请求 {}",code);
        Thread.sleep(2000);
        String weather = testService.doRequest(String.format("http://t.weather.sojson.com/api/weather/city/%s", code));
        JSONObject json = JSONUtil.parseObj(weather);
        if (json.getInt("status") == 403) {
          return   CompletableFuture.completedFuture("");
        }
        String city = json.getJSONObject("cityInfo").getStr("city");

        String cityInfo = String.format("城市：%s  , 城市数据：%s", city, json.getJSONObject("cityInfo"));
        log.info("请求结果 {}",cityInfo);

        return CompletableFuture.completedFuture(cityInfo);
    }


}
